package order

import (
	"context"
	"github.com/dtm-labs/dtmgrpc"
	"github.com/zeromicro/go-zero/core/logx"
	"go-zero-project/services/order/rpc/pb"
	productPb "go-zero-project/services/product/rpc/pb"
	"go-zero-project/services/user/api/internal/initialize/nacos"
	"go-zero-project/services/user/api/internal/svc"
	"go-zero-project/services/user/api/internal/types"
	"strconv"
)

type CreateOrderLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewCreateOrderLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateOrderLogic {
	return &CreateOrderLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *CreateOrderLogic) CreateOrder(req *types.CreateOrderReq) (resp *types.CreateOrderResp, err error) {
	// 1.获取 OrderRpc targetUrl 这里是参看 dtm go-zero集成案例 因为多年没有更新而且过于复杂
	// 看下原理就是target获取nacos实例拼接grpc的ip和port
	OrderRpcConf := l.svcCtx.Config.OrderRpc
	targetBO := nacos.NewTargetBO()
	orderTarget := targetBO.BuilderTarget(OrderRpcConf.Target)
	healthyInstance, getOrderHealthyErr := orderTarget.SelectOneHealthyInstance(l.svcCtx.Config.Nacos)
	if getOrderHealthyErr != nil {
		return nil, getOrderHealthyErr
	}
	orderBusi := healthyInstance.Ip + ":" + strconv.Itoa(int(healthyInstance.Port))
	// 2.获取 ProductRpc targetUrl
	ProductRpcConf := l.svcCtx.Config.ProductRpc
	targetBO = nacos.NewTargetBO()
	productTarget := targetBO.BuilderTarget(ProductRpcConf.Target)
	productInstance, getProductHealthyErr := productTarget.SelectOneHealthyInstance(l.svcCtx.Config.Nacos)
	if getProductHealthyErr != nil {
		return nil, getProductHealthyErr
	}
	productBusi := productInstance.Ip + ":" + strconv.Itoa(int(productInstance.Port))
	// 3.dtm 服务 这里采用的是直连的方式
	dtmUrl := l.svcCtx.Config.DtmConf.Url
	gid := dtmgrpc.MustGenGid(dtmUrl)
	// 4.创建一个saga协议的事务
	// 4.1后期可以考虑作为分布式ID
	orderId := int64(2)
	saga := dtmgrpc.NewSagaGrpc(dtmUrl, gid).Add(
		// 提交订单
		orderBusi+"/pb.order_rpc/Create",
		// 取消订单创建
		orderBusi+"/pb.order_rpc/CreateRevert",
		// 传输对象信息
		&pb.CreateRequest{
			OrderId: orderId,
			Uid:     req.Uid,
			Pid:     req.Pid,
			Amount:  req.Amount,
			Status:  0,
		},
	).Add(
		// 扣减库存
		productBusi+"/pb.product_rpc/DecrStock",
		// 反向扣减库存
		productBusi+"/pb.product_rpc/DecrStockRevert",
		// 传输对象信息
		&productPb.DecrStockRequest{
			Id:  req.Pid,
			Num: 1,
		},
	)
	// 5.事务提交
	err = saga.Submit()
	if err != nil {
		return nil, err
	}
	// 返回参数
	return &types.CreateOrderResp{Id: orderId}, nil
}
